昨天我們有了很基本的 Model 雛形,實作下去會發現其實不難理解,說來說去都離不開物件導向的概念,透過實作的過程,可以慢慢了解 ORM 的原理是什麼,如果還是有點模糊,沒關係,今天我們會繼續規劃其他功能,透過一天一天的實作,來加深更堅固的印象
話不多說直接進入主題吧
除了做 find
查詢,另一個很常用的是 all
,很常會看到在 Action 裡面搭配 index
一起使用,現在就來看看怎麼實作 all
的功能
# mavericks/lib/mavericks/file_model.rb
def self.all
files = Dir['db/tasks/*.json']
files.map { |f| FileModel.new f}
end
我們透過 Dir
來將 tasks
的 JSON 格式檔案,用 *
全部取出來,然後搭配 map
,生成一個一個的物件
接著回到 just_do 我們就可以這樣使用
# just_do/app/controller/tasks_controller.rb
class TasksController < Mavericks::Controller
def index
@tasks = FileModel.all
end
def show
@task = FileModel.find(1)
end
end
為了可以 Demo 找出所有資料的功能,需要新增多一點資料
# just_do/db/tasks/2.json
{
"title": "吃好睡飽",
"content": "每天都有滷肉飯吃"
}
再修改一下 view 的部分
<!-- just_do/app/views/tasks/index.html.erb -->
<% @tasks.each do |task| %>
<div class="row">
<div class="col-sm-6 col-lg-3">
<div class="card">
<h5 class="card-header"><%= task['title'] %></h5>
<div class="card-body">
<p class="card-text"><%= task['content'] %></p>
<span><a href="/tasks/1/edit">修改</a><a data-confirm="確定刪除?" rel="nofollow" data-method="delete" href="/tasks/1">刪除</a></span>
</div>
</div>
</div>
</div>
<% end %>
沒有意外的話,畫面上應該會出現兩筆資料,代表成功了!
剛剛相信大家應該都是手動新增第二筆資料,但如果要靠 Model 來新增呢?新增資料會稍微麻煩一點,除了要處理新增的內容以外,因為我們是用 JSON 格式檔案來代替資料庫,並不是用傳統的 SQL 語法來新增資料,所以我們其實在處理的是 要怎麼寫入一個 json 檔案
那接下來我們先在 class FileModel
底下繼續實作一個 create
# mavericks/lib/mavericks/file_model.rb
require "multi_json"
require 'byebug'
module Mavericks
module Model
class FileModel
# .
# .
# (略)
def self.create(attrs)
hash = {}
hash[:title] = attrs[:title] || ""
hash[:content] = attrs[:content] || ""
files = Dir["db/tasks/*.json"]
id = files.map { |f| f.split('/')[-1].gsub('.json','').to_i }.max + 1
File.open("db/tasks/#{id}.json", "w") do |f|
f.write <<-TEMPLATE
{
"title": "#{hash[:title]}",
"content": "#{hash[:content]}"
}
TEMPLATE
end
FileModel.new "db/tasks/#{id}.json"
end
end
end
end
有沒有發現我們一直都用 self
?那是因為我們現在都是在實作 class method
這裡說明一下實作的過程,我們在 create
裡面建立了一個 hash 來接收新增的值
hash = {}
hash[:title] = attrs[:title] || ""
hash[:content] = attrs[:content] || ""
接著尋找 db/task
底下所有的 json 檔案,然後利用 f.split('/')
後的結果,並且用 [-1]
取得陣列最後一個值,也就是 1.json
之類的檔名,之後透過 gsub
用正規表達式把 .json
去掉只留下 id
,最後在 [1, 2, 3...]
的陣列裡面,取得 max
並且 + 1,就是新檔案的 ID
files = Dir["db/tasks/*.json"]
id = files.map { |f| f.split('/')[-1].gsub('.json','').to_i }.max + 1
最後利用新的 ID 來新增一個檔案,搭配 Ruby 的 Heredoc 來定義多行字串,建立 template 內容,並且寫入檔案
File.open("db/tasks/#{id}.json", "w") do |f|
f.write <<-TEMPLATE
{
"title": "#{hash[:title]}",
"content": "#{hash[:content]}"
}
TEMPLATE
end
FileModel.new "db/tasks/#{id}.json"
回到 just_do 來測試結果,在 Controller 底下,建立一個新的 Action 來處理新增資料
# just_do/app/controllers/tasks_controller.rb
def create
attrs = {
title: '週末跟朋友聚餐',
content: '喝酒喝到飽'
}
FileModel.create(attrs)
@tasks = FileModel.all
render 'index'
end
就跟平常使用 Rails很像,用 Hash 搭配 FileModel.create
來完成新增資料的動作,最後 render
Index 頁面,記得在這之前要建立 @tasks
,因為我們在 index.html.erb
的頁面有用到 @tasks
完成後一樣打開伺服器看看結果,現在只要每次瀏覽一次 http://127.0.0.1:3001/tasks/create
,就會建立一筆新的 JSON 檔案!
「不是呀,我記得新增應該要有個表格讓我填資料才對,不是像這樣子重整就可以新增一筆資料,而且一直重整還會一直增加..」
是的,因為我們還沒處理到,怎麼接受表單 POST 過來的資料,還記得在 Rails 當中會依照 HTTP request methods
來處理相對應的行為嗎?接下來的文章我們將會開始談到這塊